package cool.taomu.toolkit.cacheable

import com.google.inject.Inject
import com.google.inject.Key
import cool.taomu.toolkit.Context
import java.io.Serializable
import java.util.Arrays
import org.aopalliance.intercept.MethodInterceptor
import org.aopalliance.intercept.MethodInvocation
import org.apache.commons.lang3.SerializationUtils
import org.slf4j.LoggerFactory
import com.google.inject.name.Names

class CachingInterceptor implements MethodInterceptor {
	val static LOG = LoggerFactory.getLogger(CachingInterceptor);

	@Inject
	Context context

	override Object invoke(MethodInvocation invocation) throws Throwable {
		var method = invocation.getMethod();
		if (method.isAnnotationPresent(Cacheable)) {
			var ann = method.getAnnotation(Cacheable)
			LOG.info("执行 {} 缓存", ann.value)
			var key = Key.get(ICacheService, Names.named(ann.value))
			var cacheService = context.injectorSupplier.get().getInstance(key)

			var methodName = method.name;
			var args = invocation.arguments;

			// 生成缓存 key：方法名 + 参数哈希值
			var cacheKey = generateCacheKey(methodName, args);

			// 尝试从缓存获取
			var cachedResult = cacheService.get(cacheKey);
			if (cachedResult !== null) {
				LOG.info("从缓存{}获取", cacheKey);
				return SerializationUtils.deserialize(cachedResult);
			}

			// 缓存未命中，执行原始方法
			var result = invocation.proceed();

			//
			LOG.info("{} 写入缓存", cacheKey);
			if (ann.expireIn == 0) {
				cacheService.put(cacheKey, SerializationUtils.serialize(result as Serializable));
			} else {
				cacheService.put(cacheKey, SerializationUtils.serialize(result as Serializable), ann.expireIn);
			}

			return result;
		}

		return invocation.proceed();
	}

	/**
	 * 生成缓存 key：方法名 + 参数 hash
	 */
	private def String generateCacheKey(String methodName, Object... args) {
		var int paramHash = Arrays.hashCode(args);
		return methodName + ":" + paramHash;
	}
}
